/**
 * 组件基类模块
 * 提供组件生命周期管理、事件处理、状态管理等基础功能
 */

import { stateManager } from './state-manager.js';

export class ComponentBase {
    constructor(container, options = {}) {
        this.container = typeof container === 'string' ? document.querySelector(container) : container;
        this.options = { ...options };
        this.state = {};
        this.eventListeners = new Map();
        this.childComponents = new Map();
        this.isDestroyed = false;
        this.subscriptions = [];
        
        // 组件ID
        this.id = options.id || this.generateId();
        
        // 初始化组件
        this.init();
    }

    /**
     * 初始化组件
     */
    init() {
        // 渲染组件
        this.render();
        
        // 绑定事件
        this.bindEvents();
        
        // 初始化子组件
        this.initChildComponents();
        
        // 组件挂载后调用
        this.onMounted();
    }

    /**
     * 渲染组件
     */
    render() {
        if (!this.container) {
            console.warn('Component container not found');
            return;
        }
        
        // 获取HTML模板
        const html = this.getTemplate();
        
        // 渲染HTML
        this.container.innerHTML = html;
        
        // 渲染后调用
        this.onRendered();
    }

    /**
     * 获取HTML模板
     * 子类应该重写此方法
     * @returns {string} - HTML模板
     */
    getTemplate() {
        return '';
    }

    /**
     * 渲染后调用
     * 子类可以重写此方法
     */
    onRendered() {
        // 子类可以重写
    }

    /**
     * 组件挂载后调用
     * 子类可以重写此方法
     */
    onMounted() {
        // 子类可以重写
    }

    /**
     * 组件销毁前调用
     * 子类可以重写此方法
     */
    onBeforeDestroy() {
        // 子类可以重写
    }

    /**
     * 组件销毁后调用
     * 子类可以重写此方法
     */
    onDestroyed() {
        // 子类可以重写
    }

    /**
     * 绑定事件
     */
    bindEvents() {
        // 子类可以重写
    }

    /**
     * 初始化子组件
     */
    initChildComponents() {
        // 子类可以重写
    }

    /**
     * 设置组件状态
     * @param {string|Object} key - 状态键或状态对象
     * @param {*} value - 状态值
     * @param {Object} options - 选项
     */
    setState(key, value, options = {}) {
        let stateChanges = {};
        
        if (typeof key === 'object') {
            stateChanges = key;
        } else {
            stateChanges[key] = value;
        }
        
        // 更新状态
        const prevState = { ...this.state };
        this.state = { ...this.state, ...stateChanges };
        
        // 如果选项中指定了不重新渲染，则只更新状态
        if (options.rerender !== false) {
            // 重新渲染组件
            this.render();
            
            // 重新绑定事件
            this.bindEvents();
            
            // 重新初始化子组件
            this.initChildComponents();
        }
        
        // 调用状态变化回调
        if (options.onStateChange) {
            options.onStateChange(this.state, prevState, stateChanges);
        }
        
        return this.state;
    }

    /**
     * 获取组件状态
     * @param {string} key - 状态键
     * @param {*} defaultValue - 默认值
     * @returns {*} - 状态值
     */
    getState(key, defaultValue = undefined) {
        if (key === undefined) {
            return { ...this.state };
        }
        
        return this.state[key] !== undefined ? this.state[key] : defaultValue;
    }

    /**
     * 添加事件监听器
     * @param {string|Element} target - 目标元素或选择器
     * @param {string} event - 事件类型
     * @param {Function} handler - 事件处理函数
     * @param {Object} options - 事件选项
     */
    addEventListener(target, event, handler, options = {}) {
        let element;
        
        if (typeof target === 'string') {
            element = this.container.querySelector(target);
        } else {
            element = target;
        }
        
        if (!element) {
            console.warn(`Element not found: ${target}`);
            return;
        }
        
        // 绑定事件
        element.addEventListener(event, handler, options);
        
        // 保存事件监听器引用，以便后续移除
        const listenerId = this.generateId();
        this.eventListeners.set(listenerId, {
            element,
            event,
            handler,
            options
        });
        
        return listenerId;
    }

    /**
     * 移除事件监听器
     * @param {string} listenerId - 监听器ID
     */
    removeEventListener(listenerId) {
        const listener = this.eventListeners.get(listenerId);
        
        if (listener) {
            listener.element.removeEventListener(
                listener.event,
                listener.handler,
                listener.options
            );
            
            this.eventListeners.delete(listenerId);
        }
    }

    /**
     * 清除所有事件监听器
     */
    clearEventListeners() {
        for (const [id, listener] of this.eventListeners.entries()) {
            listener.element.removeEventListener(
                listener.event,
                listener.handler,
                listener.options
            );
        }
        
        this.eventListeners.clear();
    }

    /**
     * 添加子组件
     * @param {string} name - 组件名称
     * @param {ComponentBase} component - 组件实例
     */
    addChildComponent(name, component) {
        this.childComponents.set(name, component);
    }

    /**
     * 获取子组件
     * @param {string} name - 组件名称
     * @returns {ComponentBase} - 组件实例
     */
    getChildComponent(name) {
        return this.childComponents.get(name);
    }

    /**
     * 移除子组件
     * @param {string} name - 组件名称
     */
    removeChildComponent(name) {
        const component = this.childComponents.get(name);
        
        if (component) {
            component.destroy();
            this.childComponents.delete(name);
        }
    }

    /**
     * 清除所有子组件
     */
    clearChildComponents() {
        for (const [name, component] of this.childComponents.entries()) {
            component.destroy();
        }
        
        this.childComponents.clear();
    }

    /**
     * 订阅状态管理器的状态变化
     * @param {string|Function} key - 状态键或监听器函数
     * @param {Function} callback - 回调函数
     * @returns {Function} - 取消订阅函数
     */
    subscribe(key, callback) {
        const unsubscribe = stateManager.subscribe(key, callback);
        this.subscriptions.push(unsubscribe);
        return unsubscribe;
    }

    /**
     * 查找DOM元素
     * @param {string} selector - 选择器
     * @returns {Element} - DOM元素
     */
    find(selector) {
        return this.container.querySelector(selector);
    }

    /**
     * 查找所有匹配的DOM元素
     * @param {string} selector - 选择器
     * @returns {NodeList} - DOM元素列表
     */
    findAll(selector) {
        return this.container.querySelectorAll(selector);
    }

    /**
     * 显示组件
     */
    show() {
        if (this.container) {
            this.container.style.display = '';
        }
    }

    /**
     * 隐藏组件
     */
    hide() {
        if (this.container) {
            this.container.style.display = 'none';
        }
    }

    /**
     * 切换组件显示状态
     */
    toggle() {
        if (this.container) {
            const isHidden = this.container.style.display === 'none';
            this.container.style.display = isHidden ? '' : 'none';
        }
    }

    /**
     * 添加CSS类
     * @param {string} className - CSS类名
     */
    addClass(className) {
        if (this.container) {
            this.container.classList.add(className);
        }
    }

    /**
     * 移除CSS类
     * @param {string} className - CSS类名
     */
    removeClass(className) {
        if (this.container) {
            this.container.classList.remove(className);
        }
    }

    /**
     * 切换CSS类
     * @param {string} className - CSS类名
     */
    toggleClass(className) {
        if (this.container) {
            this.container.classList.toggle(className);
        }
    }

    /**
     * 检查是否包含CSS类
     * @param {string} className - CSS类名
     * @returns {boolean} - 是否包含
     */
    hasClass(className) {
        return this.container ? this.container.classList.contains(className) : false;
    }

    /**
     * 设置属性
     * @param {string} name - 属性名
     * @param {*} value - 属性值
     */
    setAttribute(name, value) {
        if (this.container) {
            this.container.setAttribute(name, value);
        }
    }

    /**
     * 获取属性
     * @param {string} name - 属性名
     * @returns {string} - 属性值
     */
    getAttribute(name) {
        return this.container ? this.container.getAttribute(name) : null;
    }

    /**
     * 移除属性
     * @param {string} name - 属性名
     */
    removeAttribute(name) {
        if (this.container) {
            this.container.removeAttribute(name);
        }
    }

    /**
     * 触发自定义事件
     * @param {string} eventName - 事件名称
     * @param {*} detail - 事件详情
     */
    trigger(eventName, detail = null) {
        if (this.container) {
            const event = new CustomEvent(eventName, {
                detail,
                bubbles: true,
                cancelable: true
            });
            
            this.container.dispatchEvent(event);
        }
    }

    /**
     * 监听自定义事件
     * @param {string} eventName - 事件名称
     * @param {Function} handler - 事件处理函数
     * @param {Object} options - 事件选项
     * @returns {string} - 监听器ID
     */
    on(eventName, handler, options = {}) {
        return this.addEventListener(this.container, eventName, handler, options);
    }

    /**
     * 移除自定义事件监听器
     * @param {string} listenerId - 监听器ID
     */
    off(listenerId) {
        this.removeEventListener(listenerId);
    }

    /**
     * 生成唯一ID
     * @returns {string} - 唯一ID
     */
    generateId() {
        return `comp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }

    /**
     * 销毁组件
     */
    destroy() {
        if (this.isDestroyed) {
            return;
        }
        
        // 调用销毁前回调
        this.onBeforeDestroy();
        
        // 清除事件监听器
        this.clearEventListeners();
        
        // 销毁子组件
        this.clearChildComponents();
        
        // 取消状态订阅
        this.subscriptions.forEach(unsubscribe => unsubscribe());
        this.subscriptions = [];
        
        // 清空容器
        if (this.container) {
            this.container.innerHTML = '';
        }
        
        // 标记为已销毁
        this.isDestroyed = true;
        
        // 调用销毁后回调
        this.onDestroyed();
    }
}

export default ComponentBase;